import bpy

from bpy.types import Panel



#import engine.properties_MaterialPanel as ui_材质面板

class CustomRenderEngine(bpy.types.RenderEngine):
	# These three members are used by blender to set up the
	# RenderEngine; define its internal name, visible name and capabilities.
	bl_idname = "mbt_game_renderer"
	bl_label = "mbt 游戏引擎"
	bl_use_preview = True


	def __init__(self):
		self.scene_data = None
		self.draw_data = None

	def __del__(self):
		pass

	# This is the only method called by blender, in this example
	# we use it to detect preview rendering and call the implementation
	# in another method.
	def render(self, depsgraph):
		scene = depsgraph.scene
		scale = scene.render.resolution_percentage / 100.0
		self.size_x = int(scene.render.resolution_x * scale)
		self.size_y = int(scene.render.resolution_y * scale)

		if self.is_preview:
			pass
			#self.render_视口预览(scene)
		else:
			self.render_最总输出(scene)
		print('*-*-* render *-*-*')

	# In this example, we fill the preview renders with a flat green color.
	def render_视口预览(self, scene):
		pixel_count = self.size_x * self.size_y

		# The framebuffer is defined as a list of pixels, each pixel
		# itself being a list of R,G,B,A values
		green_rect = [[1.0, 1.0, 0.0, 1.0]] * pixel_count

		# Here we write the pixel values to the RenderResult
		result = self.begin_result(0, 0, self.size_x, self.size_y)
		layer = result.layers[0].passes["Combined"]
		layer.rect = green_rect
		self.end_result(result)

	# In this example, we fill the full renders with a flat blue color.
	def render_最总输出(self, scene):
		pixel_count = self.size_x * self.size_y

		# The framebuffer is defined as a list of pixels, each pixel
		# itself being a list of R,G,B,A values
		blue_rect = [[0.0, 0.0, 1.0, 1.0]] * pixel_count

		# Here we write the pixel values to the RenderResult
		result = self.begin_result(0, 0, self.size_x, self.size_y)
		layer = result.layers[0].passes["Combined"]
		layer.rect = blue_rect
		self.end_result(result)



	def view_update(self, context, depsgraph):
		region = context.region
		view3d = context.space_data
		scene = depsgraph.scene

		# Get viewport dimensions
		dimensions = region.width, region.height
		print('render view_update')
		if not self.scene_data:
			# First time initialization
			self.scene_data = []
			first_time = True

			# Loop over all datablocks used in the scene.
			for datablock in depsgraph.ids:
				pass
		else:
			first_time = False

			# Test which datablocks changed
			for update in depsgraph.updates:
				print("Datablock updated: ", update.id.name)

			# Test if any material was added, removed or changed.
			if depsgraph.id_type_update('MATERIAL'):
				print("Materials updated")

		# Loop over all object instances in the scene.
		if first_time or depsgraph.id_type_update('OBJECT'):
			for instance in depsgraph.object_instances:
				pass



	def view_draw(self, context, depsgraph):
		region = context.region
		scene = depsgraph.scene

		# Get viewport dimensions
		dimensions = region.width, region.height

		return
		# Bind shader that converts from scene linear to display space,
		bgl.glEnable(bgl.GL_BLEND)
		bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA);
		self.bind_display_space_shader(scene)

		if not self.draw_data or self.draw_data.dimensions != dimensions:
			self.draw_data = CustomDrawData(dimensions)

		self.draw_data.draw()

		self.unbind_display_space_shader()
		bgl.glDisable(bgl.GL_BLEND)
		



class CustomDrawData:
	def __init__(self, dimensions):
		# Generate dummy float image buffer
		self.dimensions = dimensions
		width, height = dimensions

		pixels = [0.1, 0.2, 0.1, 1.0] * width * height
		pixels = bgl.Buffer(bgl.GL_FLOAT, width * height * 4, pixels)

		# Generate texture
		self.texture = bgl.Buffer(bgl.GL_INT, 1)
		bgl.glGenTextures(1, self.texture)
		bgl.glActiveTexture(bgl.GL_TEXTURE0)
		bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
		bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA16F, width, height, 0, bgl.GL_RGBA, bgl.GL_FLOAT, pixels)
		bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
		bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
		bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)

		# Bind shader that converts from scene linear to display space,
		# use the scene's color management settings.
		shader_program = bgl.Buffer(bgl.GL_INT, 1)
		bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, shader_program);

		# Generate vertex array
		self.vertex_array = bgl.Buffer(bgl.GL_INT, 1)
		bgl.glGenVertexArrays(1, self.vertex_array)
		bgl.glBindVertexArray(self.vertex_array[0])

		texturecoord_location = bgl.glGetAttribLocation(shader_program[0], "texCoord");
		position_location = bgl.glGetAttribLocation(shader_program[0], "pos");

		bgl.glEnableVertexAttribArray(texturecoord_location);
		bgl.glEnableVertexAttribArray(position_location);

		# Generate geometry buffers for drawing textured quad
		position = [0.0, 0.0, width, 0.0, width, height, 0.0, height]
		position = bgl.Buffer(bgl.GL_FLOAT, len(position), position)
		texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
		texcoord = bgl.Buffer(bgl.GL_FLOAT, len(texcoord), texcoord)

		self.vertex_buffer = bgl.Buffer(bgl.GL_INT, 2)

		bgl.glGenBuffers(2, self.vertex_buffer)
		bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[0])
		bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, position, bgl.GL_STATIC_DRAW)
		bgl.glVertexAttribPointer(position_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)

		bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[1])
		bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, texcoord, bgl.GL_STATIC_DRAW)
		bgl.glVertexAttribPointer(texturecoord_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)

		bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, 0)
		bgl.glBindVertexArray(0)

	def __del__(self):
		bgl.glDeleteBuffers(2, self.vertex_buffer)
		bgl.glDeleteVertexArrays(1, self.vertex_array)
		bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
		bgl.glDeleteTextures(1, self.texture)

	def draw(self):
		bgl.glActiveTexture(bgl.GL_TEXTURE0)
		bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
		bgl.glBindVertexArray(self.vertex_array[0])
		bgl.glDrawArrays(bgl.GL_TRIANGLE_FAN, 0, 4);
		bgl.glBindVertexArray(0)
		bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
		
#COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}






class RenderButtonsPanel:
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = "render"
	# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here

	@classmethod
	def poll(cls, context):
		return (context.engine in cls.COMPAT_ENGINES)


class RENDER_PT_context(Panel):
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = "render"
	bl_options = {'HIDE_HEADER'}
	bl_label = ""

	@classmethod
	def poll(cls, context):
		return context.scene

	def draw(self, context):
		layout = self.layout
		layout.use_property_split = True
		layout.use_property_decorate = False

		scene = context.scene
		rd = scene.render

		if rd.has_multiple_engines:
			layout.prop(rd, "engine", text="Render Engine")
			




classes = [
	RENDER_PT_context,
	CustomRenderEngine,
]



def register():
	for c in classes:
		bpy.utils.register_class(c)

	# RenderEngines also need to tell UI Panels that they are compatible
	# Otherwise most of the UI will be empty when the engine is selected.
	# In this example, we need to see the main render image button and
	# the material preview panel.
	from bl_ui import (
			properties_render,
			properties_material,
			)
	#properties_render.RENDER_PT_render.COMPAT_ENGINES.add(CustomRenderEngine.bl_idname)
	#properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add(CustomRenderEngine.bl_idname)
	print('------------------------- properties_render -------------------------------')
	#ui_场景面板.register()
	#ui_材质面板.register()


def unregister():
	#for c in classes:
	#	bpy.utils.unregister_class(c)

	from bl_ui import (
			properties_render,
			properties_material,
			)
	#properties_render.RENDER_PT_render.COMPAT_ENGINES.remove(CustomRenderEngine.bl_idname)
	#properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.remove(CustomRenderEngine.bl_idname)
	#ui_场景面板.unregister()
	#ui_材质面板.unregister()
	




